﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Drawing.Printing;
using System.Text;
using System.Threading;
using System.Windows.Forms;

namespace HongShijin.PrintActiveX
{
	partial class CFormPrintHTML : Form
	{
		private List<HtmlViewer> _HtmlViewers = null;
		private PrintMechanically _PrintMechanically = null;

		public CFormPrintHTML()
		{
			this.InitializeComponent();
		}

		public CFormPrintHTML(PrintMechanically printMechanically)
		{
			this.InitializeComponent();
			this._PrintMechanically = printMechanically;
			this._HtmlViewers = new List<HtmlViewer>();
		}

		private void Form_Load(object sender, EventArgs e)
		{
			//if(this._PrintMechanically == null)
			//	this._PrintMechanically = new PrintMechanically();
			//this._PrintMechanically.PageSetup.PageSettings;
			this.Load_Click(sender, e);
		}

		private void Load_Click(object sender, EventArgs e)
		{
			if (this._HtmlViewers != null && this._HtmlViewers.Count > 0)
			{
				if (MessageBox.Show("如果没有必要，请不要重新加载文档！", "重新加载", MessageBoxButtons.OKCancel) == DialogResult.Cancel)
					return;
			}
			int i;
			object[] os = this._PrintMechanically.GetHtmlPrints();
			for (i = 0; i < this._HtmlViewers.Count; i++)
				this._HtmlViewers[i].IsValid = false;
			for (i = 0; i < os.Length; i++)
			{
				if (i >= this._HtmlViewers.Count)
					this._HtmlViewers.Add(new HtmlViewer());
				this._HtmlViewers[i].Index = i;
				this._HtmlViewers[i].IsValid = true;
				this._HtmlViewers[i].Content = os[i];
				this._HtmlViewers[i].SetBrowser(this, this._PrintMechanically, tpgBrowser);
			}
			timer.Enabled = true;
			tabControl.SelectedTab = tpgBrowser;
		}

		private void Draw_Click(object sender, EventArgs e)
		{
			for (int i = 0; i < this._HtmlViewers.Count; i++)
			{
				this._HtmlViewers[i].LastDraw = false;
				this._HtmlViewers[i].SetPicture(this, this._PrintMechanically, tpgImage);
			}
			tabControl.SelectedTab = tpgImage;
		}

		private void Review_Click(object sender, EventArgs e)
		{
			if (this._HtmlViewers == null || this._HtmlViewers.Count == 0)
				return;

			int i;
			for (i = 0; i < this._HtmlViewers.Count; i++)
			{
				if (!this._HtmlViewers[i].IsValid)
					break;

				if (i + 1 >= this._HtmlViewers.Count)
					i++;
			}
			if (i == 0)
				return;

			printPreview.Zoom = 1;
			printPreview.Rows = i - 1;
			printPreview.Columns = 1;
			if (printPreview.Document == null)
			{
				PrintDocument doc = new PrintDocument();
				doc.PrinterSettings = this._PrintMechanically.PrintSetup.PrinterSettings;
				doc.DefaultPageSettings = this._PrintMechanically.PageSetup.PageSettings;
				doc.DocumentName = this.GetType().Assembly.GetName().Name;
				doc.PrintPage += new PrintPageEventHandler(Document_PrintPage);
				printPreview.Document = doc;
			}
			printPreview.InvalidatePreview();
			tabControl.SelectedTab = tpgPrint;
		}

		private void Print_Click(object sender, EventArgs e)
		{
			PrintDocument doc = new PrintDocument();
			doc.PrinterSettings = this._PrintMechanically.PrintSetup.PrinterSettings;
			doc.DefaultPageSettings = this._PrintMechanically.PageSetup.PageSettings;
			doc.DocumentName = this.GetType().Assembly.GetName().Name;
			doc.PrintPage += new PrintPageEventHandler(Document_PrintPage);
			doc.Print();
		}

		private void Printer_Click(object sender, EventArgs e)
		{
			if (this._PrintMechanically.ShowPrintSetup() != (int)DialogResult.OK)
				return;

			if (this._HtmlViewers == null || this._HtmlViewers.Count == 0)
				return;

			for (int i = 0; i < this._HtmlViewers.Count; i++)
				this._HtmlViewers[i].Reset(this._PrintMechanically);
			this.Review_Click(sender, e);
			MessageBox.Show("设置已改变，请点击工具栏[重新绘图]按钮以重新绘图");
		}

		private void Pager_Click(object sender, EventArgs e)
		{
			if (this._PrintMechanically.ShowPageSetup() != (int)DialogResult.OK)
				return;

			if (this._HtmlViewers == null || this._HtmlViewers.Count == 0)
				return;

			for (int i = 0; i < this._HtmlViewers.Count; i++)
				this._HtmlViewers[i].Reset(this._PrintMechanically);
			this.Review_Click(sender, e);
			MessageBox.Show("设置已改变，请点击工具栏[重新绘图]按钮以重新绘图");
		}

		private void Close_Click(object sender, EventArgs e)
		{
			this.Close();
		}

		private void Timer_Tick(object sender, EventArgs e)
		{
			if (this._HtmlViewers == null || this._HtmlViewers.Count == 0)
				return;

			if (timer.Tag == null)
				timer.Tag = 0;
			int tag = (int)timer.Tag;
			if (tag >= this._HtmlViewers.Count)
				tag = 0;
			if (!this._HtmlViewers[tag].LastDraw)
				this._HtmlViewers[tag].SetPicture(this, this._PrintMechanically, tpgImage);
			tag++;
			timer.Tag = tag;
		}

		private void Document_PrintPage(object sender, PrintPageEventArgs e)
		{
			if (this._HtmlViewers == null || this._HtmlViewers.Count == 0)
			{
				e.Cancel = true;
				return;
			}

			if (!this._HtmlViewers[0].IsValid)
			{
				e.Cancel = true;
				return;
			}

			if (printPreview.Tag == null)
				printPreview.Tag = 0;
			int tag = (int)printPreview.Tag;
			if (tag >= this._HtmlViewers.Count)
				tag = 0;
			e.Graphics.DrawImage(this._HtmlViewers[tag].Picture.Image, e.PageSettings.PrintableArea);
			tag++;
			printPreview.Tag = tag;
			if (this._HtmlViewers.Count > tag && this._HtmlViewers[tag].IsValid)
				e.HasMorePages = true;
		}

		#region Browser Event

		public void Browser_NewWindow(object sender, CancelEventArgs e)
		{
			e.Cancel = true;
		}

		public void Browser_StatusTextChanged(object sender, EventArgs e)
		{
			if (sender is WebBrowser)
				lblStatus.Text = ((WebBrowser)sender).StatusText;
		}

		public void Browser_ProgressChanged(object sender, WebBrowserProgressChangedEventArgs e)
		{
			//
		}

		public void Browser_DocumentTitleChanged(object sender, EventArgs e)
		{
			//
		}

		public void Browser_Navigated(object sender, WebBrowserNavigatedEventArgs e)
		{
			//
		}

		#endregion
	}

	class HtmlViewer
	{
		public const int PAGE_PADDING = 20;
		public const int BROWSER_TIMEOUT = 20;
		public const int DRAW_TRIES = 5;

		public int Index = -1;
		private bool _IsValid = false;
		private bool _LastDraw = false;
		public object Content = null;
		public DateTime LoadStart = DateTime.MinValue;
		public WebBrowser Browser = null;
		public PictureBox Picture = null;

		public bool IsValid
		{
			get
			{
				return this._IsValid;
			}
			set
			{
				this._IsValid = value;
				if (this.Browser != null)
					this.Browser.Visible = value;
				if (this.Picture != null)
					this.Picture.Visible = value;
			}
		}

		public bool LastDraw
		{
			get
			{
				if (!this._IsValid)
					return true;

				return this._LastDraw;
			}
			set
			{
				this._LastDraw = value;
			}
		}

		public bool SetBrowser(CFormPrintHTML form, PrintMechanically activeX, Control parent)
		{
			if (!this._IsValid)
			{
				this.Browser.Visible = this._IsValid;
				return true;
			}

			if (this.Browser == null)
			{
				Rectangle loation = this.GetLocation(activeX);
				this.Browser = new WebBrowser();
				parent.SuspendLayout();
				parent.Controls.Add(this.Browser);
				this.Browser.Visible = this._IsValid;
				this.Browser.Top = loation.Top;
				this.Browser.Left = loation.Left;
				this.Browser.Width = loation.Width;
				this.Browser.Height = loation.Height;
				this.Browser.ScrollBarsEnabled = false;
				this.Browser.ScriptErrorsSuppressed = false;
				this.Browser.WebBrowserShortcutsEnabled = false;
				this.Browser.IsWebBrowserContextMenuEnabled = false;
				this.Browser.ObjectForScripting = activeX;
				this.Browser.NewWindow += form.Browser_NewWindow;
				this.Browser.Navigated += form.Browser_Navigated;
				this.Browser.ProgressChanged += form.Browser_ProgressChanged;
				this.Browser.StatusTextChanged += form.Browser_StatusTextChanged;
				this.Browser.DocumentTitleChanged += form.Browser_DocumentTitleChanged;
				parent.ResumeLayout();
			}
			PageSettings ps = activeX.PageSetup.PageSettings;
			//string t = "PrinterName=" + ps.PrinterName;
			string t = "PrintersCount=" + PrinterSettings.InstalledPrinters.Count;
			t = t + "&Color=" + ps.Color;
			t = t + "&Landscape=" + ps.Landscape;
			t = t + "&Bounds.Top=" + ps.Bounds.Top;
			t = t + "&Bounds.Left=" + ps.Bounds.Left;
			t = t + "&Bounds.Width=" + ps.Bounds.Width;
			t = t + "&Bounds.Height=" + ps.Bounds.Height;
			t = t + "&Margins.Top=" + ps.Margins.Top;
			t = t + "&Margins.Left=" + ps.Margins.Left;
			t = t + "&Margins.Right=" + ps.Margins.Right;
			t = t + "&Margins.Bottom=" + ps.Margins.Bottom;
			t = t + "&PaperSize.Width=" + ps.PaperSize.Width;
			t = t + "&PaperSize.Height=" + ps.PaperSize.Height;
			t = t + "&PaperSize.PaperName=" + ps.PaperSize.PaperName;
			t = t + "&PaperSource.SourceName=" + ps.PaperSource.SourceName;
			t = t + "&PrintableArea.Top=" + ps.PrintableArea.Top;
			t = t + "&PrintableArea.Left=" + ps.PrintableArea.Left;
			t = t + "&PrintableArea.Width=" + ps.PrintableArea.Width;
			t = t + "&PrintableArea.Height=" + ps.PrintableArea.Height;
			t = t + "&PrinterResolution.X=" + ps.PrinterResolution.X;
			t = t + "&PrinterResolution.Y=" + ps.PrinterResolution.Y;
			t = "DefaultPageSettings:" + Uri.EscapeUriString(t);
			if (this.Content is Uri)
				this.Browser.Navigate((Uri)this.Content, null, null, t);
			else
				this.Browser.DocumentText = this.Content + string.Empty;
			this.LoadStart = DateTime.Now;
			this._LastDraw = false;
			return true;
		}

		public bool SetPicture(CFormPrintHTML form, PrintMechanically activeX, Control parent)
		{
			if (!this._IsValid)
			{
				this.Picture.Visible = this._IsValid;
				return true;
			}

			if (this.Browser == null)
			{
				this.SetBrowser(form, activeX, parent);
				return false;
			}

			if (this.Picture == null)
			{
				Rectangle loation = this.GetLocation(activeX);
				this.Picture = new PictureBox();
				parent.SuspendLayout();
				parent.Controls.Add(this.Picture);
				this.Picture.Visible = this._IsValid;
				this.Picture.Top = loation.Top;
				this.Picture.Left = loation.Left;
				this.Picture.Width = loation.Width;
				this.Picture.Height = loation.Height;
				parent.ResumeLayout();
			}

			if (this.Browser.ReadyState != WebBrowserReadyState.Complete &&
				BROWSER_TIMEOUT > new TimeSpan(DateTime.Now.Ticks - this.LoadStart.Ticks).TotalSeconds)
			{
				this._LastDraw = false;
				return this._LastDraw;
			}

			//this._LastDraw = true;
			//for (int i = 0; i < DRAW_TRIES; i++)
			//{
			//    if (this.DrawToBitmap())
			//        return true;

			//    this.Browser.Select();
			//    this.Picture.Select();
			//}
			//this._LastDraw = false;
			//return this._LastDraw;

			this._LastDraw = this.DrawToBitmap(null);
			return this._LastDraw;

			//this._LastDraw = true;
			//Bitmap bmp = new Bitmap(this.Browser.Width, this.Browser.Height);
			//this.Browser.DrawToBitmap(bmp, new Rectangle(0, 0, this.Browser.Width, this.Browser.Height));
			//this.Picture.Image = bmp;
			//Thread trd = new Thread(new ParameterizedThreadStart(delegate(object parameter) { this.DrawToBitmap((Bitmap)parameter); }));
			//trd.Start(bmp);
			//return this._LastDraw;
		}

		private bool DrawToBitmap(Bitmap bmp)
		{
			int i, j;
			int origin;
			int white = Color.White.ToArgb();
			if (bmp == null)
			{
				bmp = new Bitmap(this.Browser.Width, this.Browser.Height);
				this.Browser.DrawToBitmap(bmp, new Rectangle(0, 0, this.Browser.Width, this.Browser.Height));
				this.Picture.Image = bmp;
			}
			this._LastDraw = true;
			for (i = 0; i < bmp.Width; i++)
			{
				for (j = 0; j < bmp.Height; j++)
				{
					origin = bmp.GetPixel(i, j).ToArgb();
					if (origin != white)
						return true;
				}
			}
			if (this.Browser.InvokeRequired)
				this.Browser.Invoke(new ThreadStart(delegate() { this.Browser.Select(); }));
			else
				this.Browser.Select();
			this._LastDraw = false;
			return this._LastDraw;
		}

		private Rectangle GetLocation(PrintMechanically activeX)
		{
			return new Rectangle(
				PAGE_PADDING,
				((int)activeX.PageSetup.PageSettings.PrintableArea.Height + PAGE_PADDING) * this.Index,
				(int)activeX.PageSetup.PageSettings.PrintableArea.Width,
				(int)activeX.PageSetup.PageSettings.PrintableArea.Height);
		}

		public void Reset(PrintMechanically activeX)
		{
			Rectangle loation = this.GetLocation(activeX);
			if (this.Browser != null)
			{
				this.Browser.Top = loation.Top;
				this.Browser.Left = loation.Left;
				this.Browser.Width = loation.Width;
				this.Browser.Height = loation.Height;
			}
			if (this.Picture != null)
			{
				this.Picture.Top = loation.Top;
				this.Picture.Left = loation.Left;
				this.Picture.Width = loation.Width;
				this.Picture.Height = loation.Height;
			}
		}
		//
	}
	//
}
//
